package infra

import (
	"fmt"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
	"io"
	"os"
	"strings"
	"wf-deploy-agent/conf"
)

var Logger = &WfLogger{buildLogger()}

type WfLogger struct {
	*zap.SugaredLogger
}

func buildLogger() *zap.SugaredLogger {
	writeSyncer := getLogWriter()
	encoder := getEncoder()
	core := zapcore.NewCore(encoder, writeSyncer, parseLevel())

	logger := zap.New(core, zap.AddCaller(), zap.AddStacktrace(zap.ErrorLevel))
	if conf.CF.Agent.Service.Env == "dev" {
		logger = logger.WithOptions(zap.Development())
	}

	zap.ReplaceGlobals(logger)

	return logger.Sugar()
}

func parseLevel() zapcore.Level {
	l := conf.CF.Logging.Level
	l = strings.ToLower(l)

	var level zapcore.Level

	switch l {
	case "debug":
		level = zapcore.DebugLevel
		break
	case "info":
		level = zapcore.InfoLevel
		break
	case "warn":
		level = zapcore.WarnLevel
		break
	case "error":
		level = zapcore.ErrorLevel
		break
	case "dpanic":
		level = zapcore.DPanicLevel
		break
	case "panic":
		level = zapcore.PanicLevel
		break
	case "fatal":
		level = zapcore.FatalLevel
		break
	default:
		level = zapcore.DebugLevel
		break
	}

	return level
}

func getEncoder() zapcore.Encoder {
	encoderConfig := zapcore.EncoderConfig{
		TimeKey:        "time",
		LevelKey:       "level",
		NameKey:        "logger",
		CallerKey:      "linenum",
		MessageKey:     "msg",
		StacktraceKey:  "stacktrace",
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.LowercaseLevelEncoder,  // 小写编码器
		EncodeTime:     zapcore.ISO8601TimeEncoder,     // ISO8601 UTC 时间格式
		EncodeDuration: zapcore.SecondsDurationEncoder, //
		EncodeCaller:   zapcore.FullCallerEncoder,      // 全路径编码器
		EncodeName:     zapcore.FullNameEncoder,
	}

	return zapcore.NewJSONEncoder(encoderConfig)
}

func getLogWriter() zapcore.WriteSyncer {
	lumberJackLogger := &lumberjack.Logger{
		Filename:   fmt.Sprintf("./logs/%s", conf.CF.Logging.File),
		MaxSize:    conf.CF.Logging.MaxSize,
		MaxBackups: conf.CF.Logging.MaxBackups,
		MaxAge:     conf.CF.Logging.MaxAge,
		Compress:   conf.CF.Logging.Compress,
	}

	ws := io.MultiWriter(lumberJackLogger, os.Stdout)

	return zapcore.AddSync(ws)
}
